/*
 * 自定义类型
 * Rust 自定义数据类型主要是通过下面这两个关键字来创建：
 * - struct： 定义一个结构体(structure)
 * - enum: 定义一个枚举类型(enumeration)
 * 而常量(constant)可以通过const 和 static 关键字来创建
 *
 * 结构体有3种类型，使用struct 关键字来创建
 * - 元组结构体(tuple struct)，事实上就是具名元组而已
 * - 经典的C语言风格结构体 (C struct)
 * - 单元结构体(unit struct), 不带字段，在泛型中很有用
 */
#[derive(Debug)]
struct Person {
    name: String,
    age: u8,
}

// 单元结构体
struct Unit;

// 元组结构体
struct Pair(i32, f32);

// 带有两个字段的结构体
struct Point {
    x: f32,
    y: f32,
}

// 结构体可以作为另一个结构体的字段
#[allow(dead_code)]
struct Rectangle {
    // 可以在空间中给定左上角和右下角在空间中的位置来指定矩形
    top_left: Point,
    bottom_right: Point,
}

fn main() {
    // 使用简单的写法初始化字段，并创建结构体
    let name = String::from("Peter");
    let age = 27;
    let peter = Person { name, age };

    // 以Debug 方式打印结构体
    println!("{:?}", peter);

    // 实例化结构体 `Point`
    let point: Point = Point {x: 10.3, y: 0.4};

    // 访问point 的字段
    println!("Point coordinates: ({}, {})", point.x, point.y);

    // 使用结构体更新语法创建新的point
    // 这样可以用到之前的point 字段
    let bottom_right = Point {x: 5.2, ..point};

    println!("second point: ({}, {})", bottom_right.x, bottom_right.y);

    // 使用`let` 绑定来解构point
    let Point { x: left_edge, y: top_edge} = point;
    println!("x = {}, y = {}", left_edge, top_edge);

    let _rectangle = Rectangle {
        // 结构体的实例化也是一个表达式
        top_left: Point { x: left_edge, y: top_edge},
        bottom_right: bottom_right,
    };

    // 实例化一个单元结构体
    let _unit = Unit;

    // 实例化一个元组结构体
    let pair = Pair(1, 0.1);

    // 访问元组结构体的字段
    println!("pair contains {:?} and {:?}", pair.0, pair.1);

    // 结构一个元组结构体
    let Pair(integer, decimal) = pair;

    println!("pair contains {:?} and {:?}", integer, decimal);
}